/* -----------------
* brief
* 1. this is code gen by tools
 */

package service

import (
	"errors"
	"fmt"
	"github.com/mjiulee/lego/utils"
	"saas_sys_base/common"
	. "saas_sys_base/modules/appmanager/models"
	configService "saas_sys_base/modules/config/service"
	tenantService "saas_sys_base/modules/tenant/service"
)

type AppManagerService struct {
	// add your model here
	appAttrService             AppAttrService
	appTenantPermissionService AppTenantPermissionService
	appProductService AppProductService
	appSuitItemService AppSuitItemService

	appConfigService           configService.AppConfigService
	tenantService              tenantService.TenantService

	tbAppTenantPermission AppTenantPermission
}

// DEPRESSED
func RegisterAllAppFromConfig() {
	var appManagerService AppManagerService
	appconfigList := appManagerService.appConfigService.GetAllAppConfig()
	for _, appconfig := range appconfigList {
		appManagerService.RegisterApp(appconfig)
	}
}

func (t *AppManagerService) RegisterApp(config *common.AppConfig) error {

	attr := NewAppAttrByAppConfig(config)
	if attr == nil {
		return errors.New("RegisterApp Failed")
	}
	attr.RunState = common.STATE_YES //表示登记app后，app状态会变为运行态，但是目前先不管这个状态
	attr.ActiveState = common.STATE_YES
	bResult := t.appAttrService.addOrUpdateAppAttr(attr, attr.MiniAppId)
	if bResult != true {
		return errors.New("RegisterApp Failed")
	}
	return nil
}

func (t *AppManagerService) GetAppPermissionByDatetime(who common.Who) *AppTenantPermission {
	return nil

}

//增加app有效期
func (t *AppManagerService) AddAppPermissionForExpireTime(appwho *common.Who, miniAppIdForSale int64, addTimeYmd utils.YearMonthDays) (*AppTenantPermission, error) {
	//先校验有没有这个租户和app
	tenant := t.tenantService.GetTenantById(appwho.TenantId)
	if tenant == nil {
		return nil, fmt.Errorf("未找到指定商家, tid<%d>", appwho.TenantId)
	}

	//app未上线不能赋予权限
	miniapp := t.appAttrService.GetAppAttrByMiniAppId(miniAppIdForSale)
	if miniapp == nil || miniapp.ActiveState != common.STATE_YES {
		return nil, errors.New("app未上线")
	}

	appTenantPermission, err := t.appTenantPermissionService.AddAppPermissionForExpireTime(appwho, miniAppIdForSale, addTimeYmd, common.APP_PERMISSION_CHECK_MODE_DATATIME)
	return appTenantPermission, err
}

func (t *AppManagerService) AddAppPermissionForExpireTime2(appwho *common.Who, miniAppIdForSale int64, addTimeYmd utils.YearMonthDays) (*AppTenantPermission, error) {
	//先校验有没有这个租户和app
	tenant := t.tenantService.GetTenantById(appwho.TenantId)
	if tenant == nil {
		return nil, fmt.Errorf("未找到指定商家, tid<%d>", appwho.TenantId)
	}

	//app未上线不能赋予权限
	miniapp := t.appAttrService.GetAppAttrByMiniAppId(miniAppIdForSale)
	if miniapp == nil || miniapp.ActiveState != common.STATE_YES {
		return nil, errors.New("app未上线")
	}

	appTenantPermission, err := t.appTenantPermissionService.AddAppPermissionForExpireTime(appwho, miniAppIdForSale, addTimeYmd, common.APP_PERMISSION_CHECK_MODE_DATETIME2)
	return appTenantPermission, err
}

//增加app有效期
func (t *AppManagerService) AddAppPermissionForAlwaysValid(appwho *common.Who, miniAppIdForSale int64) error { //TODO 后续把上面AddAppPermission的函数合在一个函数里
	//先校验有没有这个租户和app
	tenant := t.tenantService.GetTenantById(appwho.TenantId)
	if tenant == nil {
		return fmt.Errorf("未找到指定商家, tid<%d>", appwho.TenantId)
	}

	//app未上线不能赋予权限
	miniapp := t.appAttrService.GetAppAttrByMiniAppId(miniAppIdForSale)
	if miniapp == nil || miniapp.ActiveState != common.STATE_YES {
		return errors.New("app未上线")
	}

	err := t.appTenantPermissionService.AddAppPermissionForAlwaysValid(*appwho, miniAppIdForSale)
	return err
}

func (t *AppManagerService) UnsetAppPermission() error {
	return nil
}

/*
检测是否APP设置为上线状态
*/
func (t *AppManagerService) CheckAppPermission(appwho *common.Who) (bool, error) {
	rcApp := t.appAttrService.GetAppAttrByMiniAppId(appwho.MiniAppId)
	if rcApp == nil {
		return false, errors.New("APP未配置")
	}

	if rcApp.ActiveState == common.STATE_NO {
		return false, errors.New("APP未上线")
	}

	return true, nil
}

/*
检测租户是否具有这个app的权限
*/
func (t *AppManagerService) CheckAppTenantPermission(appwho *common.Who) (bool, error) {
	//特殊情况：如果app是存在的，但是tenant_id为0，表示目前未进入到任何租户，可理解为系统租户
	if appwho.TenantId == 0 {
	    hasPermission, err := t.CheckAppPermission(appwho)
	    if err != nil || !hasPermission {
		    return false, err
	    }

	    return true, err
	}

	err := t.appTenantPermissionService.CheckAppTenantPermission(appwho)

	if err != nil {
		return false, err
	}
	return true, nil
}

func (t *AppManagerService) IsTenantApp(appwho common.Who) bool {
	config, err := t.appConfigService.GetConfigByWho(appwho)
	if err != nil {
		return false
	}

	return config.App_Config_Data.Attr.Is_TenantApp
}

//核销APP商品
func (t *AppManagerService) ConsumeAppProduct(appwho *common.Who, productId int64, specId int64) error {
	//TODO：这里后续不要依赖产品里面的值，要依赖订单里面的值，这里的细节差异要提出来讨论一下
	appproduct, appspec, err := t.appProductService.GetAppProductAndSpecByIdSpecIdAndMiniAppId(productId, specId, appwho.MiniAppId)
	if err != nil {
		return err
	}

	suitItemList, _, err := t.appSuitItemService.ListAppSuitItemByAppSuitId(appproduct.AppSuitId, 1, 100)
	if err != nil {
		return err
	}


	/*now := time.Now()
	addnow := now.AddDate(0, appspec.Months, 0)
	duration := addnow.Sub(now) //计算从现在到”到期“间隔多少时间*/

	addTimeYmd := utils.YearMonthDays{
		Months: appspec.Months,
	}
	for _, suitItem :=range suitItemList {
		if suitItem.CheckMode == common.APP_PERMISSION_CHECK_MODE_DATATIME {
			//timePermission := time.Duration(appspec.Months)*time.Hour*24*31 //暂时写每月为31天，但是这样不准确
			_, err = t.AddAppPermissionForExpireTime(appwho, suitItem.MiniAppId, addTimeYmd) //暂时写死时
		} else if suitItem.CheckMode == common.APP_PERMISSION_CHECK_MODE_TIMES {
            //暂时不支持
			return errors.New("not support check times")
		} else if suitItem.CheckMode == common.APP_PERMISSION_CHECK_MODE_ALWAYS_VALID {
			err = t.AddAppPermissionForAlwaysValid(appwho, suitItem.MiniAppId)
		} else if suitItem.CheckMode == common.APP_PERMISSION_CHECK_MODE_DATETIME2 {
			//timePermission := time.Duration(appspec.Months)*time.Hour*24*31 //暂时写每月为31天，但是这样不准确
			_, err = t.AddAppPermissionForExpireTime(appwho, suitItem.MiniAppId, addTimeYmd) //暂时写死时
		}

	}

	return err
}